home *** CD-ROM | disk | FTP | other *** search
- /*
- * Modified by Phill Everson <everson@cs.bris.ac.uk> for inclusion into
- * the ALV toolkit.
- *
- */
-
- /**************************************************************************
- Copyright (c) 1988 by Hong Min
-
- compile : cc -O -o 8to1 8to1.c -lpixrect
-
- The program 8to1 converts a 8-bit depth sun raster file (both color,
- i.e. rgb are different, and grey, i.e. rgb are the same, and both
- standard format and byte-encoded format) to a 1-bit depth mono sun
- raster file. If your color image has no colormap, this program would
- provide a default grey scale color map. It implements several halftone
- algorithms from Digital Halftones by Dot Diffusion in acm Transactions
- on Graphics, such as error diffusion, ordered dither and dot diffusion
- with and without edge enhancement. Just type 8to1, it will give you
- the usage.
-
- This program was written by :
-
- Hong Min
- Computer Science Department
- SUNY at Stony Brook
- e-mail address :
- UUCP: {allegra, philabs, pyramid, research}!sbcs!rainbow
- ARPA-Internet: rainbow@sbcs.sunysb.edu
- CSnet: rainbow@suny-sb
-
- Everyone is welcome to write to me if you like the program or not.
- And welcome to optimize the code, as I haven't fooled with it to
- make it efficient yet.
-
- Enjoy!
-
- ****************************************************************************/
- #include <stdio.h>
- #include "defs.h"
- #include <sys/types.h>
- #include <pixrect/pixrect.h>
- #include <pixrect/memvar.h>
- #include <pixrect/pr_util.h>
- #include <pixrect/pr_io.h>
-
- #define WHITE 0 /* background color */
- #define BLACK ~0 /* foreground color */
- #define FALSE 0
- #define TRUE 1
- #define ALPHA 7
- #define BETA 3
- #define GAMMA 5
- #define DELTA 1
-
- hort **A, **B;
- nt ordered_dither[8][8] = {0, 32, 8, 40, 2, 34, 10, 42,
- 48, 16, 56, 24, 50, 18, 58, 26,
- 12, 44, 4, 36, 14, 46, 6, 38,
- 60, 28, 52, 20, 62, 30, 54, 22,
- 3, 35, 11, 43, 1, 33, 9, 41,
- 51, 19, 59, 27, 49, 17, 57, 25,
- 15, 47, 7, 39, 13, 45, 5, 37,
- 63, 31, 55, 23, 61, 29, 53, 21};
- nt dot_diffusion[8][8] = {34, 48, 40, 32, 29, 15, 23, 31,
- 42, 58, 56, 53, 21, 5, 7, 10,
- 50, 62, 61, 45, 13, 1, 2, 18,
- 38, 46, 54, 37, 25, 17, 9, 26,
- 28, 14, 22, 30, 35, 49, 41, 33,
- 20, 4, 6, 11, 43, 59, 57, 52,
- 12, 0, 3, 19, 51, 63, 60, 44,
- 24, 16, 8, 27, 39, 47, 55, 36};
- nt reverse_matrix[64] = {49, 21, 22, 50, 41, 13, 42, 14,
- 58, 30, 15, 43, 48, 20, 33, 5,
- 57, 29, 23, 51, 40, 12, 34, 6,
- 56, 28, 31, 59, 32, 4, 35, 7,
- 3, 39, 0, 36, 63, 27, 24, 60,
- 2, 38, 8, 44, 55, 19, 25, 61,
- 1, 37, 16, 52, 47, 11, 26, 62,
- 10, 46, 9, 45, 54, 18, 17, 53};
-
- har *progname;
- har *filename;
- ixrect *pr = 0;
-
- #define ERROR 0
- #define ORDERED 1
- #define DOT 2
-
- #ifdef STANDALONE
- ain(argc, argv, envp)
- #else
- as8to1_main(argc, argv, envp)
- #endif
- int argc;
- char **argv;
- char **envp;
- {
- int diffusion, enhancement, colour, greyscale, option;
- int default_map = FALSE;
- register int i, j;
- int levels;
- colormap_t colormap;
- register unsigned char *map;
- register struct rasterfile rh;
-
- colour = TRUE;
- diffusion = ERROR;
- enhancement = FALSE;
- progname = strsave(argv[0]);
- parse_profile(&argc, argv, envp);
-
- while ((gc = getopt(argc, argv, "rodeg")) != EOF)
- switch (gc) {
- case 'r':
- diffusion = ERROR;
- break;
- case 'o':
- diffusion = ORDERED;
- break;
- case 'd':
- diffusion = DOT;
- break;
- case 'e':
- enhancement = TRUE;
- break;
- case 'g':
- colour = FALSE;
- break;
- case '?':
- errflag++;
- break;
- }
-
- if (errflag)
- error((char *) 0, "Usage: %s: [-r] [-o] [-d] [-e] [-g] [infile] [outfile]", progname);
-
- for (stream = 0; optind < argc; stream++, optind++)
- if (stream < 2 && strcmp(argv[optind], "-") != 0)
- if (freopen(argv[optind], mode[stream], f[stream]) == NULL)
- error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
-
- setup_greylevelmap();
-
- /* Load the input rasterfile header */
- if (pr_load_header(stdin, &rh) == PIX_ERR)
- error(PR_IO_ERR_RASREAD);
-
- if (rh.ras_depth != 8)
- error("infile is not a 8 bits deep");
-
- /* Load the colormap */
- colormap.type = RMT_NONE;
- colormap.map[0] = (unsigned char *) malloc(256);
- colormap.map[1] = (unsigned char *) malloc(256);
- colormap.map[2] = (unsigned char *) malloc(256);
- if (pr_load_colormap(stdin, &rh, &colormap) == PIX_ERR)
- error("read colormap error");
-
- if (colormap.type != RMT_NONE &&
- (colormap.type != RMT_EQUAL_RGB || colormap.length < 256))
- error("input has unsupported colormap type or length\n");
-
- if ((colormap.type == RMT_NONE) && (colormap.length == 0)) {
- default_map = TRUE;
- map = greylevelmap;
- colour = FALSE;
- }
- if (rh.ras_type != RT_OLD && rh.ras_type != RT_STANDARD &&
- !(pr = pr_load_image(stdin, &rh, &colormap))) {
- fprintf(stderr, "error reading rasterfile\n");
- exit(1);
- }
- option = diffusion;
- if (enhancement)
- option += 3;
- if (colour)
- option += 6;
-
- /* Write new header */
- rh.ras_type = RT_STANDARD;
- rh.ras_depth = 1;
- rh.ras_length = mpr_linebytes(rh.ras_width, 1) * rh.ras_height;
- rh.ras_maptype = RMT_NONE;
- rh.ras_maplength = 0;
-
- if (pr_dump_header(stdout, &rh, (colormap_t *) 0) == PIX_ERR)
- error("pr_dump_header failed");
-
- if (rh.ras_width <= 0 || rh.ras_height <= 0)
- exit(1);
- else {
- A = (short **) malloc((rh.ras_width + 3) * sizeof(short *));
- B = (short **) malloc((rh.ras_width + 3) * sizeof(short *));
- for (i = 0; i < rh.ras_width + 3; i++) {
- A[i] = (short *) malloc((rh.ras_height + 3) * sizeof(short));
- B[i] = (short *) malloc((rh.ras_height + 3) * sizeof(short));
- }
- }
-
- if (!default_map)
- map = colormap.map[0];
-
- if (pr)
- switch (option) {
- case 6:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 0:
- error_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 0, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 7:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 1:
- ordered_dither_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 0, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 8:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 2:
- dot_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 0, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 9:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 3:
- error_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 1, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 10:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 4:
- ordered_dither_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 1, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- case 11:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 5:
- dot_diffusion_image(rh.ras_width, rh.ras_height,
- map, (u_char *) mpr_d(pr)->md_image, stdout,
- 1, mpr_d(pr)->md_linebytes - rh.ras_width);
- break;
- }
- else
- switch (option) {
- case 6:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 0:
- error_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 0,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 7:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 1:
- ordered_dither_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 0,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 8:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 2:
- dot_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 0,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 9:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 3:
- error_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 1,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 10:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 4:
- ordered_dither_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 1,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- case 11:
- map = (unsigned char *) malloc(256);
- color_map_3_to_1(colormap, map);
- case 5:
- dot_diffusion_file(rh.ras_width, rh.ras_height,
- map, stdin, stdout, 1,
- mpr_linebytes(rh.ras_width, 8) - rh.ras_width);
- break;
- }
- }
-
- olor_map_3_to_1(colormap, map)
- register colormap_t colormap;
- register unsigned char *map;
- {
- register unsigned long tmp, i;
-
- for (i = 0; i < 256; i++) {
- tmp = colormap.map[0][i] * 77 + colormap.map[1][i] * 151 + colormap.map[2][i] * 28;
- map[i] = tmp >> 8;
- }
- }
-
-
- dge_enhancement(width, height, off)
- register int width, height, off;
- {
- register int i, j, x, y;
-
- B[off][off] = A[off][off] * 6 - A[off][off + 1] - A[off + 1][off] - A[off + 1][off + 1];
- B[off][off + height - 1] = A[off][off + height - 1] * 6 - A[off][off + height - 2] - A[off + 1][off + height - 1] - A[off + 1][off + height - 2];
- B[off + width - 1][off] = A[off + width - 1][off] * 6 - A[off + width - 1][off + 1] - A[off + width - 2][off] - A[off + width - 2][off + 1];
- B[off + width - 1][off + height - 1] = A[off + width - 1][off + height - 1] * 6 - A[off + width - 1][off + height - 2] - A[off + width - 2][off + height - 1] - A[off + width - 2][off + height - 2];
-
- for (i = 1; i < width - 1; i++)
- B[off + i][off + 0] = A[off + i][off + 0] * 6 - A[off + i - 1][off + 0] - A[off + i + 1][off + 0] - A[off + i - 1][off + 1] - A[off + i][off + 1] - A[off + i + 1][off + 1];
- for (i = 1; i < width - 1; i++)
- B[off + i][off + height - 1] = A[off + i][off + height - 1] * 6 - A[off + i - 1][off + height - 1] - A[off + i + 1][off + height - 2] - A[off + i - 1][off + height - 2] - A[off + i][off + 1] - A[off + i + 1][off + height - 2];
- for (i = 1; i < height - 1; i++)
- B[off + 0][off + i] = A[off + 0][off + i] * 6 - A[off + 0][off + i - 1] - A[off + 0][off + i + 1] - A[off + 1][off + i - 1] - A[off + 1][off + i] - A[off + 1][off + i + 1];
- for (i = 1; i < height - 1; i++)
- B[off + width - 1][off + i] = A[off + width - 1][off + i] * 6 - A[off + width - 1][off + i - 1] - A[off + width - 1][off + i + 1] - A[off + width - 2][off + i - 1] - A[off + width - 2][off + i] - A[off + width - 2][off + i + 1];
-
- for (i = 1; i < width - 1; i++)
- for (j = 1; j < height - 1; j++) {
- B[off + i][off + j] = A[off + i][off + j] * 10;
- for (x = i - 1; x <= i + 1; x++)
- for (y = j - 1; y <= j + 1; y++)
- B[off + i][off + j] -= A[off + x][off + y];
- }
-
- for (i = 0; i < width; i++)
- for (j = 0; j < height; j++)
- A[off + i][off + j] = B[off + i][off + j];
- }
-
-
- nt
- ndex(x, y, w, pad)
- register int x, y, w, pad;
- {
- return (x + y * (w + pad));
- }
-
- rror_diffusion(width, height, out, edge)
- register int width, height;
- register FILE *out;
- register int edge;
- {
- register int err, mono_pad;
- register u_short dtmp;
- register u_long i, j;
-
- mono_pad = mpr_linebytes(width, 1) * 8 - width;
-
- if (edge)
- edge_enhancement(width, height, 1);
-
- for (j = 1; j < height + 1; j++) {
- for (i = 1; i < width + 1; i++) {
- dtmp <<= 1;
- if (A[i][j] > 128)
- err = A[i][j] - 256;
- else {
- err = A[i][j];
- dtmp |= 1;
- }
- A[i + 1][j] += (err * ALPHA) >> 4;
- A[i - 1][j + 1] += (err * BETA) >> 4;
- A[i][j + 1] += (err * GAMMA) >> 4;
- A[i + 1][j + 1] += (err * DELTA) >> 4;
- if (((i - 1) % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- for (i = width + 1; i <= width + mono_pad; i++) {
- dtmp <<= 1;
- if (((i - 1) % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- }
- }
-
- /* Compute pixel values using error diffusion */
- rror_diffusion_image(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register u_char *in;
- register FILE *out;
- register int edge_enhance, pad;
- {
- register int i, j;
-
- for (j = 1; j < height + 1; j++)
- for (i = 1; i < width + 1; i++)
- A[i][j] = map[*(in + index(i - 1, j - 1, width, pad))];
-
- error_diffusion(width, height, out, edge_enhance);
- }
-
-
- /* Compute pixel values using error diffusion */
- rror_diffusion_file(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register FILE *in, *out;
- register int edge_enhance, pad;
- {
- register int i, j, c;
-
- for (j = 1; j < height + 1; j++) {
- for (i = 1; i < width + 1; i++) {
- if ((c = getc(in)) == EOF) {
- fprintf(stderr, "error reading raster data!\n");
- exit(1);
- }
- A[i][j] = map[c];
- }
- for (i = width; i < width + pad; i++)
- if ((c = getc(in)) == EOF)
- fprintf(stderr, "error reading raster data!\n");
- }
-
- error_diffusion(width, height, out, edge_enhance);
- }
-
- rdered(width, height, out, edge)
- register int width, height;
- register FILE *out;
- register int edge;
- {
- register int mono_pad;
- register u_short dtmp;
- register u_long i, j;
-
- mono_pad = mpr_linebytes(width, 1) * 8 - width;
-
- if (edge)
- edge_enhancement(width, height, 0);
-
- for (j = 0; j < 8; j++)
- for (i = 0; i < 8; i++)
- ordered_dither[i][j] = ordered_dither[i][j] * 4 + 2;
-
- for (j = 0; j < height; j++) {
- for (i = 0; i < width; i++) {
- dtmp <<= 1;
- if (A[i][j] >= ordered_dither[i % 8][j % 8])
- dtmp |= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- for (i = width; i < width + mono_pad; i++) {
- dtmp <<= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- }
- }
-
- rdered_dither_image(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register u_char *in;
- register FILE *out;
- register int edge_enhance, pad;
- {
- register int i, j;
-
- for (j = 0; j < height; j++)
- for (i = 0; i < width; i++)
- A[i][j] = 256 - map[*(in + index(i, j, width, pad))];
-
- ordered(width, height, out, edge_enhance);
- }
-
-
- rdered_dither_file(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register FILE *in, *out;
- register int edge_enhance, pad;
- {
- register int i, j, c;
-
- for (j = 0; j < height; j++) {
- for (i = 0; i < width; i++) {
- if ((c = getc(in)) == EOF) {
- fprintf(stderr, "error reading raster data!\n");
- exit(1);
- }
- A[i][j] = 256 - map[c];
- }
- for (i = width; i < width + pad; i++)
- if ((c = getc(in)) == EOF)
- fprintf(stderr, "error reading raster data!\n");
- }
-
- ordered(width, height, out, edge_enhance);
- }
-
- nt
- eight(x, y)
- register int x, y;
- {
- return (3 - x * x - y * y);
- }
-
- ot(width, height, out, edge)
- register int width, height;
- register FILE *out;
- register int edge;
- {
- register int k, u, v, err, w, mono_pad;
- register u_short dtmp;
- register u_long i, j;
-
- mono_pad = mpr_linebytes(width, 1) * 8 - width;
-
- if (edge)
- edge_enhancement(width, height, 0);
-
- for (k = 0; k < 64; k++) {
- for (i = reverse_matrix[k] / 8; i < width; i += 8)
- for (j = reverse_matrix[k] % 8; j < height; j += 8) {
- if (A[i][j] > 128)
- B[i][j] = 0;
- else
- B[i][j] = 1;
- err = A[i][j] - (1 - B[i][j]) * 256;
- w = 0;
- for (u = i - 1; u <= i + 1; u++)
- for (v = j - 1; v <= j + 1; v++)
- if ((u >= 0) && (v >= 0) && (dot_diffusion[u % 8][v % 8] > k))
- w += weight(u - i, v - j);
- if (w > 0) {
- for (u = i - 1; u <= i + 1; u++)
- for (v = j - 1; v <= j + 1; v++)
- if ((u >= 0) && (v >= 0) && (dot_diffusion[u % 8][v % 8] > k))
- A[u][v] += err * weight(u - i, v - j) / w;
- }
- }
- }
-
- for (j = 0; j < height; j++) {
- for (i = 0; i < width; i++) {
- dtmp <<= 1;
- if (B[i][j])
- dtmp |= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- for (i = width; i < width + mono_pad; i++) {
- dtmp <<= 1;
- if ((i % 16) == 15) {
- putc(dtmp >> 8, out);
- putc(dtmp, out);
- }
- }
- }
- }
-
-
- ot_diffusion_image(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register u_char *in;
- register FILE *out;
- register int edge_enhance, pad;
- {
- register int i, j;
-
- for (j = 0; j < height; j++)
- for (i = 0; i < width; i++)
- A[i][j] = map[*(in + index(i, j, width, pad))];
-
- dot(width, height, out, edge_enhance);
- }
-
- ot_diffusion_file(width, height, map, in, out, edge_enhance, pad)
- register int width, height;
- register unsigned char *map;
- register FILE *in, *out;
- register int edge_enhance, pad;
- {
- register int i, j, c;
-
- for (j = 0; j < height; j++) {
- for (i = 0; i < width; i++) {
- if ((c = getc(in)) == EOF) {
- fprintf(stderr, "error reading raster data!\n");
- exit(1);
- }
- A[i][j] = map[c];
- }
- for (i = width; i < width + pad; i++)
- if ((c = getc(in)) == EOF)
- fprintf(stderr, "error reading raster data!\n");
- }
-
- dot(width, height, out, edge_enhance);
- }
-